import json
from copy import deepcopy
from importlib import import_module
from collections.abc import MutableMapping

from bald_spider.settings import default_settings


class SettingsManager(MutableMapping):
    def __init__(self,value=None):
        self.attributes = {}
        self.set_settings(default_settings)
        self.update_settings(value)

    def __getitem__(self, item):
        if item not in self:
            return None
        return self.attributes[item]

    def __setitem__(self, key, value):
        self.set(key, value)

    def __delitem__(self, key):
        self.delete(key)

    def __iter__(self):
        return iter(self.attributes)

    def __len__(self):
        return len(self.attributes)

    def __str__(self):
        return f"<Settings values = {self.attributes}>"

    def __contains__(self, item):
        return item in self.attributes

    __repr__ = __str__

    def copy(self):
        return deepcopy(self)

    def get(self, item, default=None):
        return self[item] if self[item] is not None else default

    def getint(self, item):
        return int(self.get(item))

    def getfloat(self, item):
        return float(self.get(item))

    def getbool(self, item, default=False):
        got = self.get(item, default)
        try:
            return bool(int(got))
        except ValueError:
            if got in ("True", "true", "TRUE"):
                return True
            if got in ("False", "false", "FALSE"):
                return False
            else:
                raise ValueError(
                    "Supported values are (True or False) or (TRUE or FALSE) or (true or false) or (0 or 1)")

    def getlist(self, item, default=None):
        value = self.get(item, default or [])
        if isinstance(value, str):
            return value.split(',')
        return list(value)

    def getdict(self, item, default=None):
        value = self.get(item, default or {})
        if isinstance(value, str):
            return json.loads(value)
        return dict(value)

    def set(self, item, value):
        self.attributes[item] = value

    def delete(self, item):
        del self.attributes[item]

    def set_settings(self, module):
        if isinstance(module, str):
            module = import_module(module)
        for key in dir(module):
            if key.isupper():
                self.set(key, getattr(module, key))

    def update_settings(self, module):
        if module is not None:
            for key,value in module.items():
                self.set(key, value)